/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package managedbean.RawMaterialPurchase;

import java.util.ArrayList;
import java.util.Collection;
import javax.annotation.PostConstruct;
import javax.ejb.EJB;
import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import javax.faces.context.FacesContext;
import javax.faces.event.ActionEvent;
import merlion.scm.rmpm.entity.RawMaterial;
import merlion.scm.rmpm.entity.RawMaterialSupplyInformation;
import merlion.scm.rmpm.entity.Supplier;
import merlion.scm.rmpm.entity.SupplierContactRecord;
import merlion.scm.rmpm.session.RawMaterialPurchaseSessionBeanLocal;
import org.primefaces.context.RequestContext;

/**
 *
 * @author Kenn
 */
@ManagedBean
@ViewScoped
public class SupplierManagerBean {

    @EJB
    private RawMaterialPurchaseSessionBeanLocal rmpSessionBean;
    
    private Supplier supplier;
    private String statusMsg;
    private SupplierContactRecord contact;
    private SupplierContactRecord contactBackup;
    private RawMaterialSupplyInformation rmsi;
    private RawMaterialSupplyInformation rmsiBackup;
    
    //--------------------------------------------------------------------------
    //                          Constructor
    //--------------------------------------------------------------------------
    public SupplierManagerBean() {
        supplier = (Supplier) FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get("supplier");
        FacesContext.getCurrentInstance().getExternalContext().getSessionMap().remove("supplier");
        
        statusMsg = (String) FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get("statusMsg");
        FacesContext.getCurrentInstance().getExternalContext().getSessionMap().remove("statusMsg");
        
    }
    
    @PostConstruct
    public void init(){
        
        if(supplier == null){
            supplier = new Supplier();
            supplier.setSupplierId(rmpSessionBean.generateSupplierId());
        }
        
        contact = new SupplierContactRecord();
        contactBackup = new SupplierContactRecord();
        rmsi = new RawMaterialSupplyInformation();
        rmsiBackup = new RawMaterialSupplyInformation();
    }
    
    //--------------------------------------------------------------------------
    //                          Manager Bean Methods
    //--------------------------------------------------------------------------
    
    public void addContactRecord(ActionEvent event){
        
        //Validate contact record
        RequestContext context = RequestContext.getCurrentInstance();
        boolean valid = true;
        // Contact Name: Required, Alphabetic
        if (!isNotEmpty(contact.getName())) {
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "Name is required", ""));
            valid = false;
        }
        if (!isAlphabetic(contact.getName())) {
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "Name can only contain alphabetical characters.", ""));
            valid = false;
        }
        // Contact Designation: Required, Alphabetic
        if (!isNotEmpty(contact.getJobTitle())) {
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "Designation cannot be empty.", ""));
            valid = false;
        }
        if (!isAlphabetic(contact.getJobTitle())) {
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "Designation can only contain alphabetical characters.", ""));
            valid = false;
        }
        // Contact Phone: Required
        if (!isNotEmpty(contact.getPhone())) {
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "Phone cannot be empty.", ""));
            valid = false;
        }
        // Contact Email: Required, is valid email
        if (!isNotEmpty(contact.getEmail())) {
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "E-mail cannot be empty.", ""));
            valid = false;
        }
        if (!isValidEmailAddress(contact.getEmail())) {
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "E-mail is not valid.", ""));
            valid = false;
        }
        boolean executiveExist = false;
        for(SupplierContactRecord scr: supplier.getContacts()){
            if(scr.getExecutive() == true)
                executiveExist = true;
        }
        if(contact.getExecutive() == true && executiveExist == true){
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "Executive exists. There can only be one executive.", ""));
            valid = false;
        }
        context.addCallbackParam("valid", valid);
        if(!valid)
            return;
        
        supplier.getContacts().add(contact);
        contact = new SupplierContactRecord();
    }
    
    public void cancelAddContactRecord(ActionEvent event){
        contact = new SupplierContactRecord();
    }
    
    public void editContact(ActionEvent event){
        contact = (SupplierContactRecord)event.getComponent().getAttributes().get("selected");
        contactBackup = contact.clone();
    }
    
    public void cancelEditContactRecord(ActionEvent event){
        contact.setEmail(contactBackup.getEmail());
        contact.setExecutive(contactBackup.getExecutive());
        contact.setJobTitle(contactBackup.getJobTitle());
        contact.setName(contactBackup.getName());
        contact.setPhone(contactBackup.getPhone());
        
        contact = new SupplierContactRecord();
    }
    
    public void updateEditContactRecord(ActionEvent event){
        
        //Validate contact record
        RequestContext context = RequestContext.getCurrentInstance();
        boolean valid = true;
        // Contact Name: Required, Alphabetic
        if (!isNotEmpty(contact.getName())) {
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "Name is required", ""));
            valid = false;
        }
        if (!isAlphabetic(contact.getName())) {
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "Name can only contain alphabetical characters.", ""));
            valid = false;
        }
        // Contact Designation: Required, Alphabetic
        if (!isNotEmpty(contact.getJobTitle())) {
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "Designation cannot be empty.", ""));
            valid = false;
        }
        if (!isAlphabetic(contact.getJobTitle())) {
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "Designation can only contain alphabetical characters.", ""));
            valid = false;
        }
        // Contact Phone: Required
        if (!isNotEmpty(contact.getPhone())) {
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "Phone cannot be empty.", ""));
            valid = false;
        }
        // Contact Email: Required, is valid email
        if (!isNotEmpty(contact.getEmail())) {
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "E-mail cannot be empty.", ""));
            valid = false;
        }
        if (!isValidEmailAddress(contact.getEmail())) {
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "E-mail is not valid.", ""));
            valid = false;
        }
        boolean executiveExist = false;
        ArrayList<SupplierContactRecord> scrList = new ArrayList<SupplierContactRecord>(supplier.getContacts());
        scrList.remove(contact);
        for(SupplierContactRecord scr: scrList){
            if(scr.getExecutive() == true)
                executiveExist = true;
        }
        if(contact.getExecutive() == true && executiveExist == true){
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "Executive exists. There can only be one executive.", ""));
            valid = false;
        }
        context.addCallbackParam("valid", valid);
        if(!valid)
            return;
        
        contact = new SupplierContactRecord();
    }
    
    public void removeContact(ActionEvent event){
        contact = (SupplierContactRecord)event.getComponent().getAttributes().get("selected");
    }
    
    public void confirmRemoveContact(ActionEvent event){
        supplier.getContacts().remove(contact);
        contact = new SupplierContactRecord();
    }
    
    public void cancelRemoveContact(ActionEvent event){
        contact = new SupplierContactRecord();
    }
    
    public Collection<RawMaterial> getAllRawMaterial() {
        return rmpSessionBean.getAllRawMaterial();
    }
    
    public void addRawMaterial(ActionEvent event){        
        
        //Validate raw material
        RequestContext context = RequestContext.getCurrentInstance();
        boolean valid = true;
        // Contact Name: Required, Alphabetic
        if (rmsi.getRawMaterial() == null || rmsi.getRawMaterial().getName().equals("")) {
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "Raw material is required", ""));
            valid = false;
        }
        if (rmsi.getCurrency() == null){
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "Currency is required", ""));
            valid = false;
        }
        if ((double)rmsi.getUnitPriceSGD() <= 0.0 && (double)rmsi.getUnitPriceUSD() <= 0.0){
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "Unit price cannot be zero or negative", ""));
            valid = false;
        }
        boolean rmExist = false;
        for(RawMaterialSupplyInformation r: supplier.getRawMaterialsSupplied()){
            if(rmsi.getRawMaterial().equals(r.getRawMaterial())){
                rmExist = true;
            }
        }
        if(rmExist){
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "Raw material exists in supply list", ""));
            valid = false;
        }
        context.addCallbackParam("valid", valid);
        if(!valid)
            return;
        
        rmsi.setSupplier(supplier);
        if(rmsi.getCurrency()){
            rmsi.setUnitPriceUSD((double)rmsi.getUnitPriceSGD()/(double)1.2);
            rmsi.setUnitLotPriceUSD((double)rmsi.getUnitPriceSGD()/(double)1.2*(double)rmsi.getRawMaterial().getLotSize());
        } else {
            rmsi.setUnitPriceSGD((double)rmsi.getUnitPriceUSD()*(double)1.2);
            rmsi.setUnitLotPriceSGD((double)rmsi.getUnitPriceUSD()/(double)1.2*(double)rmsi.getRawMaterial().getLotSize());
        }
        supplier.getRawMaterialsSupplied().add(rmsi);
        
        rmsi = new RawMaterialSupplyInformation();
    }
    
    public void cancelAddRawMaterial(ActionEvent event){
        rmsi = new RawMaterialSupplyInformation();
    }
    
    public void setRawMaterial(ActionEvent event){
        System.out.println("INVOKE Edit Raw Material");
        rmsi = (RawMaterialSupplyInformation) event.getComponent().getAttributes().get("selected");
        rmsiBackup = rmsi.clone();
    }
    
    public void updateEditRawMaterial(ActionEvent event){
        
        //Validate raw material
        RequestContext context = RequestContext.getCurrentInstance();
        boolean valid = true;
        // Contact Name: Required, Alphabetic
        if (rmsi.getRawMaterial() == null || rmsi.getRawMaterial().getName().equals("")) {
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "Raw material is required", ""));
            valid = false;
        }
        if (rmsi.getCurrency() == null){
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "Currency is required", ""));
            valid = false;
        }
        if ((double)rmsi.getUnitPriceSGD() <= 0.0 && (double)rmsi.getUnitPriceUSD() <= 0.0){
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "Unit price cannot be zero or negative", ""));
            valid = false;
        }
        boolean rmExist = false;
        ArrayList<RawMaterialSupplyInformation> list = new ArrayList<RawMaterialSupplyInformation>(supplier.getRawMaterialsSupplied());
        list.remove(rmsi);
        for(RawMaterialSupplyInformation r: list){
            if(rmsi.getRawMaterial().equals(r.getRawMaterial())){
                rmExist = true;
            }
        }
        if(rmExist){
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "Raw material exists in supply list", ""));
            valid = false;
        }
        context.addCallbackParam("valid", valid);
        if(!valid)
            return;
        
        if(rmsi.getCurrency()){
            rmsi.setUnitPriceUSD((double)rmsi.getUnitPriceSGD()/(double)1.2);
            rmsi.setUnitLotPriceUSD((double)rmsi.getUnitPriceSGD()/(double)1.2*(double)rmsi.getRawMaterial().getLotSize());
        } else {
            rmsi.setUnitPriceSGD((double)rmsi.getUnitPriceUSD()*(double)1.2);
             rmsi.setUnitLotPriceSGD((double)rmsi.getUnitPriceUSD()/(double)1.2*(double)rmsi.getRawMaterial().getLotSize());
        }
        
        rmsi = new RawMaterialSupplyInformation();
    }
    
    public void cancelEditRawMaterial(ActionEvent event){
        
        rmsi.setRawMaterial(rmsiBackup.getRawMaterial());
        rmsi.setSupplier(rmsiBackup.getSupplier());
        rmsi.setUnitPriceSGD(rmsiBackup.getUnitPriceSGD());
        rmsi.setUnitPriceUSD(rmsiBackup.getUnitPriceUSD());
        rmsi.setUnitLotPriceSGD(rmsiBackup.getUnitLotPriceSGD());
        rmsi.setUnitLotPriceUSD(rmsiBackup.getUnitLotPriceUSD());
        rmsi.setCurrency(rmsiBackup.getCurrency());
        
        rmsi = new RawMaterialSupplyInformation();
    }
    
    public void removeRawMaterial(ActionEvent event){
        rmsi = (RawMaterialSupplyInformation) event.getComponent().getAttributes().get("selected");
    }
    
    public void confirmRemoveRawMaterial(ActionEvent event){
        supplier.getRawMaterialsSupplied().remove(rmsi);
        
        rmsi = new RawMaterialSupplyInformation();
    }
    
    public void cancelRemoveRawMaterial(ActionEvent event){
        rmsi = new RawMaterialSupplyInformation();
    }
    
    public String addNewSupplier(){
        
        //Validate
        boolean valid = true;
        if (supplier.getSupplierName() == null || supplier.getSupplierName().equals("")){
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "Supplier name is required", ""));
            valid = false;
        }
        if (supplier.getSupplierAddress().getAddressLine1().equals("")){
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "Address Line 1 is required", ""));
            valid = false;
        }
        if (supplier.getSupplierAddress().getStateName().equals("")){
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "State is required", ""));
            valid = false;
        }
        if (supplier.getSupplierAddress().getCity().equals("")){
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "City is required", ""));
            valid = false;
        }
        if (supplier.getSupplierAddress().getCountry().equals("")){
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "Country is required", ""));
            valid = false;
        }
        if (supplier.getSupplierAddress().getZipCode().equals("")){
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "Zip code is required", ""));
            valid = false;
        }
        boolean executiveExist = false;
        for(SupplierContactRecord cr: supplier.getContacts()){
            if(cr.getExecutive())
                executiveExist = true;
        }
        if(!executiveExist){
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "Contact list must have supplier executive", ""));
            valid = false;
        }
        if(supplier.getRawMaterialsSupplied().isEmpty()){
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "Supply list cannot be empty", ""));
            valid = false;
        }
        if(!valid)
            return null;
        
        supplier = rmpSessionBean.saveSupplier(supplier);
        
        if (supplier != null) {
            FacesContext.getCurrentInstance().getExternalContext().getSessionMap().put("statusMsg", "Supplier added successfully.");
        } else {
            FacesContext.getCurrentInstance().getExternalContext().getSessionMap().put("statusMsg", "Failed to add supplier. Please try again.");
        }
        
        return "addSupplierStatus?faces-redirect=true";
    }
    
    public String updateSupplier(){
        //Validate
        boolean valid = true;
        if (supplier.getSupplierName() == null || supplier.getSupplierName().equals("")){
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "Supplier name is required", ""));
            valid = false;
        }
        if (supplier.getSupplierAddress().getAddressLine1().equals("")){
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "Address Line 1 is required", ""));
            valid = false;
        }
        if (supplier.getSupplierAddress().getStateName().equals("")){
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "State is required", ""));
            valid = false;
        }
        if (supplier.getSupplierAddress().getCity().equals("")){
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "City is required", ""));
            valid = false;
        }
        if (supplier.getSupplierAddress().getCountry().equals("")){
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "Country is required", ""));
            valid = false;
        }
        if (supplier.getSupplierAddress().getZipCode().equals("")){
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "Zip code is required", ""));
            valid = false;
        }
        boolean executiveExist = false;
        for(SupplierContactRecord cr: supplier.getContacts()){
            if(cr.getExecutive())
                executiveExist = true;
        }
        if(!executiveExist){
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "Contact list must have supplier executive", ""));
            valid = false;
        }
        if(supplier.getRawMaterialsSupplied().isEmpty()){
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "Supply list cannot be empty", ""));
            valid = false;
        }
        if(!valid)
            return null;
        
        supplier = rmpSessionBean.saveSupplier(supplier);
        
        if (supplier != null) {
            FacesContext.getCurrentInstance().getExternalContext().getSessionMap().put("statusMsg", "Supplier updated successfully.");
        } else {
            FacesContext.getCurrentInstance().getExternalContext().getSessionMap().put("statusMsg", "Failed to update supplier. Please try again.");
        }
        
        return "viewSupplierListEditStatus?faces-redirect=true";
    }
    
    //--------------------------------------------------------------------------
    //                          Getter and Setter
    //--------------------------------------------------------------------------

    public SupplierContactRecord getContact() {
        return contact;
    }

    public void setContact(SupplierContactRecord contact) {
        this.contact = contact;
    }

    public RawMaterialSupplyInformation getRmsi() {
        return rmsi;
    }

    public void setRmsi(RawMaterialSupplyInformation rmsi) {
        this.rmsi = rmsi;
    }

    public Supplier getSupplier() {
        return supplier;
    }

    public void setSupplier(Supplier supplier) {
        this.supplier = supplier;
    }

    public String getStatusMsg() {
        return statusMsg;
    }

    public void setStatusMsg(String statusMsg) {
        this.statusMsg = statusMsg;
    }

    public SupplierContactRecord getContactBackup() {
        return contactBackup;
    }

    public void setContactBackup(SupplierContactRecord contactBackup) {
        this.contactBackup = contactBackup;
    }

    public RawMaterialSupplyInformation getRmsiBackup() {
        return rmsiBackup;
    }

    public void setRmsiBackup(RawMaterialSupplyInformation rmsiBackup) {
        this.rmsiBackup = rmsiBackup;
    }
    
    //-------------------------------------------------------------------------
    //                                 Validator
    //-------------------------------------------------------------------------
    private boolean isValidEmailAddress(String email) {
        if(email.matches("[\\w\\.-]*[a-zA-Z0-9_]@[\\w\\.-]*[a-zA-Z0-9]\\.[a-zA-Z][a-zA-Z\\.]*[a-zA-Z]")){
            return true;
        }
        return false;
    }


    private boolean isAlphabetic(String str) {
        if (str.matches("[a-zA-Z\\s]*")) {
            return true;
        } else {
            return false;
        }
    }

    private boolean isAlphanumeric(String str) {

        if (str.matches("[a-zA-z0-9\\s]*")) {
            return true;
        } else {
            return false;
        }

    }

    private boolean isNumeric(String str) {
        if (str.matches("[0-9]*")) {
            return true;
        } else {
            return false;
        }

    }

    private boolean isNotEmpty(String str) {
        if (str == null) {
            return false;
        }
        if (str.equals("")) {
            return false;
        }
        return true;
    }
}
